﻿using CheckIn.UserInfoHost.Applications;
using CheckIn.UserInfoHost.DBModels;
using CheckIn.UserInfoHost.Infrastructures;
using JMS;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Threading.Tasks;
using System.Linq;
using Way.EntityDB;
using Microsoft.Extensions.Logging;
using Way.Lib;
using CheckIn.UserInfoHost.Dtos;
using EJ;

namespace CheckIn.UserInfoHost.Controllers
{
    [Authorize]
    public class AccountController : BaseController<UserInfoDBContext>
    {
        private readonly WechatService _wechatService;
        private readonly AuthService _authService;
        private readonly ILogger<AccountController> _logger;

        public AccountController(WechatService wechatService, AuthService authService, ILogger<AccountController> logger)
        {
            _wechatService = wechatService;
            _authService = authService;
            _logger = logger;
        }

        [AllowAnonymous]
        public string test()
        {
            _logger.LogDebug($"登陆人ip:{this.GetRemoteIpAddress(new string[] { "127.0.0.1" })}");
            return this.Headers.ToJsonString(true);
        }
        #region 登录
        /// <summary>
        /// 用户完成登录
        /// </summary>
        /// <param name="wechat_code">小程序的code</param>
        /// <returns>返回token</returns>
        [Category("登录")]
        [AllowAnonymous]
        public async Task<string> Login(string wechat_code)
        {

            var db = this.CurrentDBContext;

            var loginRet = await _wechatService.Login(wechat_code);

            var user = await db.UserInfo.FirstOrDefaultAsync(m => m.OpenId == loginRet.openid);
            if (user == null)
            {
                user = new DBModels.UserInfo
                {
                    OpenId = loginRet.openid,
                    CreateTime = Global.Timer.Now
                };
                await db.InsertAsync(user);
            }

            return _authService.CreateToken(user.id.Value, user.OpenId);
        }
        #endregion

        #region 用户信息
        /// <summary>
        /// 设置姓名、头像
        /// 错误码：
        /// 1=昵称已被使用
        /// </summary>
        /// <param name="name">昵称</param>
        /// <param name="avator">头像url</param>
        /// <returns></returns>
        [Category("用户信息")]
        public async Task SetUserInfo(string name, string avator)
        {
            name = name?.Trim();
            var db = this.CurrentDBContext;
            if (await db.UserInfo.AnyAsync(m => m.id != this.UserId && EF.Functions.Like(m.Name, name)))
                throw new ServiceException(1, "昵称已被使用");
            db.BeginTransaction();
            var user = await db.UserInfo.FirstOrDefaultAsync(m => m.id == this.UserId);
            user.Name = name;
            user.Avator = avator;
            await db.UpdateAsync(user);
        }

        /// <summary>
        /// 获取当前用户的信息
        /// </summary>
        /// <returns></returns>
        [Category("用户信息")]
        public async Task<UserInfoExt> GetUserInfo()
        {
            return await (from m in this.CurrentDBContext.UserInfo
                          where m.id == this.UserId
                          select new UserInfoExt
                          {
                              UserId = m.id.Value,
                              Name = m.Name,
                              Avator = m.Avator,
                          }).FirstOrDefaultAsync();
        }
        #endregion

        #region 找人
        /// <summary>
        /// 查找用户
        /// </summary>
        /// <param name="name">昵称</param>
        /// <returns>返回uid</returns>
        [Category("找人")]
        public async Task<UserInfoExt> FindUser(string name)
        {
            name = name?.Trim();
            var ret = await (from m in this.CurrentDBContext.UserInfo
                             where EF.Functions.ILike(m.Name, name)
                             select new UserInfoExt
                             {
                                 UserId = m.id.Value,
                                 Name = m.Name,
                                 Avator = m.Avator,
                             }).FirstOrDefaultAsync();
            ret.IsFllow = await this.CurrentDBContext.UserFllow.AnyAsync(m => m.UserId == this.UserId && m.TargetId == ret.UserId);
            return ret;
        }
        #endregion

        #region 关注
        /// <summary>
        /// 关注其他用户
        /// </summary>
        /// <param name="userId">目标用户id</param>
        /// <returns>返回uid</returns>
        [Category("关注")]
        public async Task Fllow(long userId)
        {
            if (userId == this.UserId)
            {
                throw new ServiceException("自己不能关注自己");
            }

            this.CurrentDBContext.BeginTransaction();

            if (await this.CurrentDBContext.UserFllow.AnyAsync(m => m.TargetId == userId && m.UserId == this.UserId) == false)
            {
                var fllow = new UserFllow
                {
                    UserId = this.UserId,
                    TargetId = userId,
                    CreateTime = Global.Timer.Now
                };

                try
                {
                    await this.CurrentDBContext.InsertAsync(fllow);
                }
                catch (RepeatException)
                {
                    return;
                }

                var user = new UserInfo();
                user.SetValue(m => m.FllowCount == m.FllowCount + 1);
                await this.CurrentDBContext.UpdateAsync(user, m => m.id == userId);
            }
        }

        /// <summary>
        /// 取消关注
        /// </summary>
        /// <param name="userId">目标用户id</param>
        /// <returns></returns>
        [Category("关注")]
        public async Task CancelFllow(long userId)
        {
            this.CurrentDBContext.BeginTransaction();

            if (await this.CurrentDBContext.DeleteAsync<UserFllow>(m => m.TargetId == userId && m.UserId == this.UserId) > 0)
            {
                var user = new UserInfo();
                user.SetValue(m => m.FllowCount == m.FllowCount - 1);
                await this.CurrentDBContext.UpdateAsync(user, m => m.id == userId);
            }
        }

        /// <summary>
        /// 获取当前用户所有关注的人
        /// </summary>
        /// <returns></returns>
        [Category("关注")]
        public async Task<UserInfoExt[]> GetMyFllows()
        {
            return await (from m in this.CurrentDBContext.UserInfo
                          from j in this.CurrentDBContext.UserFllow
                          where m.id == j.TargetId && j.UserId == this.UserId
                          select new UserInfoExt
                          {
                              UserId = m.id.Value,
                              Avator = m.Avator,
                              Name = m.Name,
                          }).ToArrayAsync();
        }

        /// <summary>
        /// 获取所有关注我的人
        /// </summary>
        /// <returns></returns>
        [Category("关注")]
        public async Task<UserInfoExt[]> GetFllowToMe()
        {
            return await (from m in this.CurrentDBContext.UserInfo
                          from j in this.CurrentDBContext.UserFllow
                          where m.id == j.UserId && j.TargetId == this.UserId
                          select new UserInfoExt
                          {
                              UserId = m.id.Value,
                              Avator = m.Avator,
                              Name = m.Name,
                          }).ToArrayAsync();
        }
        #endregion

        #region 内容检查
        /// <summary>
        /// 检查文字内容是否合规，如果报错，表示不合规
        /// </summary>
        /// <param name="content"></param>
        /// <returns></returns>
        [Category("内容检查")]
        public async Task TextCheck(string content)
        {
            var db = this.CurrentDBContext;
            var openId = await db.UserInfo.Where(m => m.id == this.UserId).Select(m => m.OpenId).FirstOrDefaultAsync();
            await _wechatService.TextCheck(content, openId);
        }

        /// <summary>
        /// 检查图片内容是否合规，如果报错，表示不合规
        /// </summary>
        /// <param name="img_url">图片url</param>
        /// <returns></returns>
        [Category("内容检查")]
        public async Task ImageCheck(string img_url)
        {
            var db = this.CurrentDBContext;
            var openId = await db.UserInfo.Where(m => m.id == this.UserId).Select(m => m.OpenId).FirstOrDefaultAsync();
            await _wechatService.ImageCheck(img_url, openId);
        }
        #endregion
    }
}
